<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Mockjs</title>
</head>

<body>
    打开浏览器控制台查看结果。<br />
    <a href="http://mockjs.com/" target="_blank">文档</a>
    <script src="https://unpkg.com/mockjs@1.1.0/dist/mock.js"></script>
    <script src="https://unpkg.com/axios@0.26.1/dist/axios.min.js"></script>
    <script>
        // ==============================
        //            字符串
        // ==============================
        // 'name|min-max': string # 生成 1-10 范围内随机数量的星型符号
        var data = Mock.mock({
            "star|1-10": "★"
        })
        console.log('[字符串] 生成随机数量的星型符号 = ', data.star, typeof (data), data);
        // console.log(' = ', data.star, typeof (data), data);
        // 'name|count': string # 重复多次字符串内容
        data = Mock.mock({
            "star|3": "★★★"
        })
        console.log('[字符串] 重复多次字符串内容 = ', data.star, typeof (data), data);

        // ==============================
        //            数值
        // ==============================
        // 'name|+1': number # 自增长数值（失效）
        data = Mock.mock({
            "id|+1": 100
        })
        console.log('[数值] 自增长数值（失效） = ', data.id, typeof (data), data);
        // 'name|min-max': number # 生成 1-100 范围内的随机数
        data = Mock.mock({
            "luck|1-100": 100
        })
        console.log('[数值] 生成随机整数 = ', data.luck, typeof (data), data);
        // 'name|min-max.dmin-dmax': number # 生成 1-100 随机整数，带随机 1-10 位小数
        data = Mock.mock({
            "money|1-100.1-10": 1
        })
        console.log('[数值] 生成随机小数 = ', data.money, typeof (data), data);

        // ==============================
        //            布尔值
        // ==============================
        // 'name|1': boolean
        data = Mock.mock({
            "status|1": true
        })
        console.log('[布尔值] 生成随机布尔值 = ', data.status, typeof (data), data);
        // 'name|min-max': boolean
        data = Mock.mock({
            "status|1-2": true
        })
        console.log('[布尔值] 生成随机布尔值 = ', data.status, typeof (data), data);

        // ==============================
        //            对象
        // ==============================
        // 'name|count': object # 从预设值中随机返回 2-4 个元素，返回类型是对象
        data = Mock.mock({
            "object|2-4": {
                "310000": "上海市",
                "320000": "江苏省",
                "330000": "浙江省",
                "340000": "安徽省"
            }
        })
        console.log('[对象] 生成随机对象 = ', data.object, typeof (data), data);

        // ==============================
        //            数组
        // ==============================
        // 'name|1-2': array # 随机返回 1-2 个项目，返回类型是数组
        data = Mock.mock({
            "array|1-2": [
                "AMD",
                "CMD",
                "UMD"
            ]
        })
        console.log('[数组] 生成随机简单数组 = ', data.array, typeof (data), data);

        data = Mock.mock({
            "array|1-10": [
                {
                    "name|+1": [
                        "Hello",
                        "Mock.js",
                        "!"
                    ]
                }
            ]
        })
        console.log('[数组] 生成随机对象数组 = ', data.array, typeof (data), data);

        // ==============================
        //            常用对象
        // ==============================
        data = Mock.mock({
            'userInfo': {
                'id': '@id', // 随机编号
                'id2': '@increment', // 自增长编号
                'guid': '@guid', // 全球唯一编码
                'serialid|1-5': /\d{5,10}\-/,
                'user_name': '@string("lower", 5)', // 5位小写字符
                'password': '@string(8,16)', // 8-16位字符串
                'salt': '@string(6)', // 6位字符串
                'real_name': '@cname', // 中文姓名
                'email': '@email',
                'mobile': /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
                'blance': '@float(0,100,1,5)',
                'score': '@integer(100,1000)',
                'address': '',
                'region': '@region', // 区域（华北、华南）
                'province': '@province', // 省份
                'ciry': '@city(true)', // 城市
                'country': '@county(true)', // 区镇
                'street': '@ctitle(6,10)',
                'zip': '@zip', // 邮编
                'gender': '@integer(0,2)',
                'age': '@integer(18,100)',
                'login_ip': '@ip',
                'login_count': '@integer(0,100)',
                'favorite': '@range(1,10)',
                'remark': '@ctitle(0,50)', // 0-50位中文
                'homepage': '@url', // 网址
                'signature': '@cparagraph(0,100)', // 个性签名
                'avatar': '@image("200x100", "#894FC4", "#FFF", "png", "描述!")',
                'created_time': '@datetime("yyyy-MM-dd HH:mm:ss")',
                'date_ymd': '@date("yyyy-MM-dd")',
            }
        })
        console.log('[常用对象] 生成用户对象 = ', data.userInfo, typeof (data), data);

        // ==============================
        //            常用数组
        // ==============================
        data = Mock.mock({
            'list|1-10': [{
                'id': '@id', // 随机编号
                'id2': '@increment', // 自增长编号
                'guid': '@guid', // 全球唯一编码
                'serialid|1-5': /\d{5,10}\-/,
                'user_name': '@string("lower", 5)', // 5位小写字符
                'password': '@string(8,16)', // 8-16位字符串
                'salt': '@string(6)', // 6位字符串
                'real_name': '@cname', // 中文姓名
                'email': '@email',
                'mobile': /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
                'blance': '@float(0,100,1,5)',
                'score': '@integer(100,1000)',
                'address': '',
                'region': '@region', // 区域（华北、华南）
                'province': '@province', // 省份
                'ciry': '@city(true)', // 城市
                'country': '@county(true)', // 区镇
                'street': '@ctitle(6,10)',
                'zip': '@zip', // 邮编
                'gender': '@integer(0,2)',
                'age': '@integer(18,100)',
                'login_ip': '@ip',
                'login_count': '@integer(0,100)',
                'favorite': '@range(1,10)',
                'remark': '@ctitle(0,50)', // 0-50位中文
                'homepage': '@url', // 网址
                'signature': '@cparagraph(0,100)', // 个性签名
                'avatar': '@image("200x100", "#894FC4", "#FFF", "png", "描述!")',
                'created_time': '@datetime("yyyy-MM-dd HH:mm:ss")',
                'date_ymd': '@date("yyyy-MM-dd")',
            }]
        })
        console.log('[常用对象] 生成用户数组 = ', data.list, typeof (data), data);

        // ==============================
        //            Ajax拦截
        // ==============================
        Mock.mock('/api/test', {
            success: '@boolean',
            message: '@ctitle',
            code: '@integer(1000,9999)',
            data: {
                total: '@integer(0,10)',
                current_page: 1,
                last_age: '@integer(1,5)',
                'data|1-10': [{
                    'id': '@id', // 随机编号
                    'id2': '@increment', // 自增长编号
                    'guid': '@guid', // 全球唯一编码
                    'serialid|1-5': /\d{5,10}\-/,
                    'user_name': '@string("lower", 5)', // 5位小写字符
                    'password': '@string(8,16)', // 8-16位字符串
                    'salt': '@string(6)', // 6位字符串
                    'real_name': '@cname', // 中文姓名
                    'email': '@email',
                    'mobile': /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
                    'blance': '@float(0,100,1,5)',
                    'score': '@integer(100,1000)',
                    'address': '',
                    'region': '@region', // 区域（华北、华南）
                    'province': '@province', // 省份
                    'ciry': '@city(true)', // 城市
                    'country': '@county(true)', // 区镇
                    'street': '@ctitle(6,10)',
                    'zip': '@zip', // 邮编
                    'gender': '@integer(0,2)',
                    'age': '@integer(18,100)',
                    'login_ip': '@ip',
                    'login_count': '@integer(0,100)',
                    'favorite': '@range(1,10)',
                    'remark': '@ctitle(0,50)', // 0-50位中文
                    'homepage': '@url', // 网址
                    'signature': '@cparagraph(0,100)', // 个性签名
                    'avatar': '@image("200x100", "#894FC4", "#FFF", "png", "描述!")',
                    'created_time': '@datetime("yyyy-MM-dd HH:mm:ss")',
                    'date_ymd': '@date("yyyy-MM-dd")',
                }],
            },
        })
        axios.get('/api/test').then(res => { console.log('[/api/test] 请求返回结果 = ', res.data); }).catch(ex => {
            console.log('错误：', ex);
        })


        // ==============================
        //      Ajax拦截 - 资源控制器
        // ==============================
        // ThinkPHP 资源控制器: index, read, save, update, delete
        // Laravel 资源控制器: index, show, store, update, destory
        class MembersMock {
            // 显示资源列表
            index(option) {
                let param = this.parseOption(option);
                console.log('[MembersMock] 显示资源列表 param=', param, '&option=', option);
                return Mock.mock({
                    success: '@boolean',
                    message: '@ctitle',
                    code: '@integer(1000,9999)',
                    data: {
                        total: '@integer(0,10)',
                        current_page: 1,
                        last_age: '@integer(1,5)',
                        'data|1-10': [{
                            // 'id': '@id', // 随机编号
                            'id': '@increment', // 自增长编号
                            'guid': '@guid', // 全球唯一编码
                            'serialid|1-5': /\d{5,10}\-/,
                            'user_name': '@string("lower", 5)', // 5位小写字符
                            'password': '@string(8,16)', // 8-16位字符串
                            'salt': '@string(6)', // 6位字符串
                            'real_name': '@cname', // 中文姓名
                            'email': '@email',
                            'mobile': /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
                            'blance': '@float(0,100,1,5)',
                            'score': '@integer(100,1000)',
                            'address': '',
                            'region': '@region', // 区域（华北、华南）
                            'province': '@province', // 省份
                            'ciry': '@city(true)', // 城市
                            'country': '@county(true)', // 区镇
                            'street': '@ctitle(6,10)',
                            'zip': '@zip', // 邮编
                            'gender': '@integer(0,2)',
                            'age': '@integer(18,100)',
                            'login_ip': '@ip',
                            'login_count': '@integer(0,100)',
                            'favorite': '@range(1,10)',
                            'remark': '@ctitle(0,50)', // 0-50位中文
                            'homepage': '@url', // 网址
                            'signature': '@cparagraph(0,100)', // 个性签名
                            'avatar': '@image("200x100", "#894FC4", "#FFF", "png", "描述!")',
                            'created_time': '@datetime("yyyy-MM-dd HH:mm:ss")',
                            'date_ymd': '@date("yyyy-MM-dd")',
                        }],
                    },
                })
            }

            // 显示指定的资源
            read(option) {
                let param = this.parseOption(option);
                console.log('[MembersMock] 显示指定的资源 param=', param, '&option=', option);
                if (!param.id || param.id.trim().length == 0) {
                    return this.stdMessage(false, '参数无效');
                }
                return Mock.mock({
                    success: '@boolean',
                    message: '@ctitle',
                    code: '@integer(1000,9999)',
                    'data': {
                        'id': '@id', // 随机编号
                        'id2': '@increment', // 自增长编号
                        'guid': '@guid', // 全球唯一编码
                        'serialid|1-5': /\d{5,10}\-/,
                        'user_name': '@string("lower", 5)', // 5位小写字符
                        'password': '@string(8,16)', // 8-16位字符串
                        'salt': '@string(6)', // 6位字符串
                        'real_name': '@cname', // 中文姓名
                        'email': '@email',
                        'mobile': /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/,
                        'blance': '@float(0,100,1,5)',
                        'score': '@integer(100,1000)',
                        'address': '',
                        'region': '@region', // 区域（华北、华南）
                        'province': '@province', // 省份
                        'ciry': '@city(true)', // 城市
                        'country': '@county(true)', // 区镇
                        'street': '@ctitle(6,10)',
                        'zip': '@zip', // 邮编
                        'gender': '@integer(0,2)',
                        'age': '@integer(18,100)',
                        'login_ip': '@ip',
                        'login_count': '@integer(0,100)',
                        'favorite': '@range(1,10)',
                        'remark': '@ctitle(0,50)', // 0-50位中文
                        'homepage': '@url', // 网址
                        'signature': '@cparagraph(0,100)', // 个性签名
                        'avatar': '@image("200x100", "#894FC4", "#FFF", "png", "描述!")',
                        'created_time': '@datetime("yyyy-MM-dd HH:mm:ss")',
                        'date_ymd': '@date("yyyy-MM-dd")',
                    }
                })
            }

            // 保存新建的资源
            save(option) {
                let param = this.parseOption(option);
                console.log('[MembersMock] 保存新建的资源 param=', param, '&option=', option);
                if (!param.user_name || param.user_name.trim().length == 0) {
                    return this.stdMessage(false, '用户名是必填项');
                }
                return Mock.mock({
                    success: '@boolean',
                    message: '@ctitle',
                    code: '@integer(1000,9999)',
                    'data': {
                        'id': '@id', // 随机编号
                    }
                })
            }

            // 保存更新的资源
            update(option) {
                let param = this.parseOption(option);
                console.log('[MembersMock] 保存更新的资源 param=', param, '&option=', option);
                if (!param.id || isNaN(param.id)) {
                    return this.stdMessage(false, '参数无效');
                }
                if (!param.user_name || param.user_name.trim().length == 0) {
                    return this.stdMessage(false, '用户名无效');
                }
                return Mock.mock({
                    success: '@boolean',
                    message: '@ctitle',
                    code: '@integer(1000,9999)',
                    'data': {
                        'id': param.id, // 随机编号
                    }
                })

            }

            // 删除指定资源
            delete(option) {
                let param = this.parseOption(option);
                console.log('[MembersMock] 删除指定资源 param=', param, '&option=', option);
                if (!param.id || param.id.trim().length == 0) {
                    return this.stdMessage(false, '参数无效');
                }
                return Mock.mock({
                    success: '@boolean',
                    message: '@ctitle',
                    code: '@integer(1000,9999)',
                    'data': {
                        'id': param.id, // 随机编号
                    }
                })
            }

            // 解析参数
            parseOption(option) {
                // option= {url:'/api/read?id=1', type:'GET', data:null}
                let param = {}
                if (option.url.indexOf('?') > -1) {
                    new URLSearchParams(option.url.substring(option.url.indexOf('?') + 1)).forEach((v, k) => {
                        param[k] = v;
                    })
                }
                if (option.body) {
                    if (option.body instanceof FormData) {
                        option.body.forEach((v, k) => {
                            param[k] = v;
                        })
                    } else {
                        param = JSON.parse(option.body);
                    }
                }
                return param;
            }

            // 返回标准消息对象
            stdMessage(success, message, data = '', code = 0) {
                return {
                    success: success,
                    message: message,
                    data: data,
                    code: code,
                }
            }
        }
        const membersMock = new MembersMock();

        // 语法: Mock.mock( rurl, rtype, template )
        // 说明: rurl 支持正则表达式, rtype 必须小写
        // see: https://blog.csdn.net/dadiyang/article/details/82825163
        Mock.mock(RegExp('/api/members/index' + ".*"), option => membersMock.index(option))
        Mock.mock(RegExp('/api/members/read' + ".*"), option => membersMock.read(option))
        Mock.mock('/api/members/save', 'post', option => membersMock.save(option))
        Mock.mock('/api/members/update', 'put', option => membersMock.update(option))
        Mock.mock(RegExp('/api/members/delete' + ".*"), 'delete', option => membersMock.delete(option))

        // axios.request(config)
        // axios.get(url[, config])
        // axios.delete(url[, config])
        // axios.head(url[, config])
        // axios.post(url[, data[, config]])
        // axios.put(url[, data[, config]])
        // axios.patch(url[, data[, config]])
        // see: https://www.kancloud.cn/yunye/axios/234845
        // 示例: axios.get('/api/members/index?page=1&page_size=2') 等效 axios.get('/api/members/index', { params: { page: 1, page_size: 20, search: '王' } })
        axios.get('/api/members/index', { params: { page: 1, page_size: 20, search: '王' } }).then(res => { console.log('[/api/members/index] 请求返回结果 = ', res.data); }).catch(ex => {
            console.log('错误：', ex);
        })
        axios.get('/api/members/read', { params: { id: 1, } }).then(res => { console.log('[/api/members/read] 请求返回结果 = ', res.data); }).catch(ex => {
            console.log('错误：', ex);
        })
        axios.post('/api/members/save', { id: 1, user_name: 'abc' }).then(res => { console.log('[/api/members/save] 请求返回结果 = ', res.data); }).catch(ex => {
            console.log('错误：', ex);
        })
        axios.put('/api/members/update', { id: 1, user_name: 'abc' }).then(res => { console.log('[/api/members/update] 请求返回结果 = ', res.data); }).catch(ex => {
            console.log('错误：', ex);
        })
        axios.delete('/api/members/delete', { params: { id: 1, } }).then(res => { console.log('[/api/members/delete] 请求返回结果 = ', res.data); }).catch(ex => {
            console.log('错误：', ex);
        })
    </script>
</body>

</html>